package com.suray.basic.wcs.plc.pojo.oper.lifter;

import com.suray.basic.wcs.plc.core.PlcOffset;
import com.suray.basic.wcs.plc.enums.AbutmentLayer;
import com.suray.basic.wcs.plc.enums.CargoState;
import com.suray.basic.wcs.plc.enums.Location;
import com.suray.basic.wcs.plc.enums.PlcDeviceType;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LoggerUtil;

import java.io.IOException;

public class TwoDirectionRgvLifterOper extends LifterOper {
    //读两向车状态
    private final PlcOffset TWO_DIRECTION_RGV_STATE = new PlcOffset(4, null);
    //读两向车故障
    private final PlcOffset TWO_DIRECTION_RGV_LIFTER_ERROR = new PlcOffset(7, null);
    //写两向车货位状态
    private final PlcOffset WRITE_CARGO_STATE = new PlcOffset(22, null);
    //读货物状态
    private final PlcOffset READ_CARGO_STATE = new PlcOffset(5, null);
    //任务一键恢复
    private final PlcOffset WRITE_TASK_RECOVER = new PlcOffset(23, null);
    //读取货物清除标记
    private final static PlcOffset CARGO_SIGN = new PlcOffset(22, null);
    //读两向车故障
    private final PlcOffset TWO_DIRECTION_RGV_ERR = new PlcOffset(11, null);
    private final PlcOffset LOCK_T = new PlcOffset(10, null);


    public TwoDirectionRgvLifterOper(PlcDeviceType plcDeviceType, int startNo, String deviceName, int deviceNo, Coord coord,
                                     Location location, Coord lockLocation, long deviceId, Integer gridzMax,
                                     Integer gridzRelative, int plcId) {
        super(plcDeviceType, startNo, deviceName, deviceNo, coord, location, lockLocation, deviceId, gridzMax,
                gridzRelative, plcId);
    }

    /**
     * 判断提升机内里有无两向车
     *
     * @retur true有两向车
     */
    public boolean isHasTwoDirectionRgv() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_STATE.getAddressOffset(), bit1)) == 1;
    }

    /**
     * 判断提升机两向车是否运行
     *
     * @return true运行中
     */
    public boolean isTwoDirectionRgvRuning() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_STATE.getAddressOffset(), bit2)) == 1;
    }

    /**
     * 判断提升机内两向车是否到位
     *
     * @return true提升机内两向车到位
     */
    public boolean isTwoDirectionRgvArrive() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_STATE.getAddressOffset(), bit3)) == 1;
    }

    /**
     * 提升机两向车是否取货中
     *
     * @return true两向车取货中
     */
    public boolean isTwoDirectionRgvGetCargo() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_STATE.getAddressOffset(), bit4)) == 1;
    }

    /**
     * 提升机两向车是否放货中
     *
     * @return true两向车放货中
     */
    public boolean isTwoDirectionRgvPutCargo() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_STATE.getAddressOffset(), bit5)) == 1;
    }

    /**
     * 判断两向车上是否有货
     *
     * @return true两向车上有货
     */
    public boolean isTwoDirectionRgvHasCargo() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_STATE.getAddressOffset(), bit6)) == 1;
    }

    /**
     * 判断当前层是否为二向车层
     *
     * @return
     */
    public boolean isTwoDirectionRgvLayerArrived() {
        return readPlc(new PlcOffset(8, bit13)) == 1;
    }

    /**
     * 读提升机对应层数是否有货
     *
     * @param floor    层 提升机内部的层传1-10任意数字
     * @param location 位置
     * @return
     */
    @Override
    public boolean isPalletExisted(Integer floor, Location location) {
        if (floor > 99 || floor < 1) {
            throw new IllegalArgumentException("输送线状态层数参数异常");
        }
        if (location.equals(Location.LEFT)) {
            int index = READ_CARGO_STATE.getAddressOffset();
            int k = (bit1 + (floor - 1)) % 16;
            index = index + (int) ((floor - 1) / 16);
            return readPlc(new PlcOffset(index, k)) == 1;
        } else if (location.equals(Location.RIGHT)) {
            int index = READ_CARGO_STATE.getAddressOffset();
            int k = (bit1 + 10 + (floor - 1)) % 16;
            index = index + (int) ((floor - 1) * 3 / 16);
            return readPlc(new PlcOffset(index, k)) == 1;
        } else if (location.equals(Location.INSIDE)) {
            return isHaveCargo();
        } else {
            throw new IllegalArgumentException("传入位置数参数异常");
        }
    }

    /**
     * 提升机两向车前限位超限是否故障
     *
     * @return true 提升机两向车前限位超限故障
     */
    public boolean isTwoDirectionRgvFontLimited() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit1)) == 1;
    }

    /**
     * 提升机两向车后限位超限是否故障
     *
     * @return true 提升机两向车后限位超限故障
     */
    public boolean isTwoDirectionRgvBackLimited() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit2)) == 1;
    }

    /**
     * 1方向取货有四向车
     *
     * @return true 1方向取货有四向车
     */
    public boolean oneDirectionGetCargoHasRgv() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit3)) == 1;
    }

    /**
     * 3方向取货有四向车
     *
     * @return true 3方向取货有四向车
     */
    public boolean threeDirectionGetCargoHasRgv() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit4)) == 1;
    }

    @Override
    public boolean isFacilityProblem(Integer floor, Location location) {
        return false;
    }

    /**
     * 1方向取货无托盘
     *
     * @return true 1方向取货无托盘
     */
    public boolean oneDirectionGetNoPallet() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit5)) == 1;
    }

    /**
     * 3方向取货无托盘
     *
     * @return true 3方向取货无托盘
     */
    public boolean threeDirectionGetNoPallet() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit6)) == 1;
    }

    /**
     * 1方向放货有四向车
     *
     * @return true 1方向放货有四向车
     */
    public boolean oneDirectionPutCargoHasRgv() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit7)) == 1;
    }

    /**
     * 3方向放货有四向车
     *
     * @return true 3方向放货有四向车
     */
    public boolean threeDirectionPutHasRgv() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit8)) == 1;
    }

    /**
     * 1方向放货有托盘
     *
     * @return true 1方向放货有托盘
     */
    public boolean oneDirectionPutCargoHasPallet() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit9)) == 1;
    }

    /**
     * 3方向放货有托盘
     *
     * @return true 3方向放货有托盘
     */
    public boolean threeDirectionPutHasPallet() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_LIFTER_ERROR.getAddressOffset(), bit10)) == 1;
    }

    /**
     * 提升机轴偏差过大
     *
     * @return
     */
    public boolean lifterAxleOverrun() {
        return readPlc(new PlcOffset(LOCK_T.getAddressOffset(), bit8)) == 1;
    }

    /**
     * 两向车行驶驱动器报警
     *
     * @return
     */
    public boolean twoDirectionDriveErr() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit1)) == 1;
    }

    /**
     * 两向车托盘驱动器报警
     *
     * @return
     */
    public boolean twoDirectionPalletDriveErr() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit2)) == 1;
    }

    /**
     * 一方向手动行驶超限
     *
     * @return
     */
    public boolean oneDirectionRunOverrun() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit3)) == 1;
    }

    /**
     * 三方向手动行驶超限
     *
     * @return
     */
    public boolean threeDirectionRunOverrun() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit4)) == 1;
    }

    /**
     * 托盘升极限
     *
     * @return
     */
    public boolean palletUpOverrun() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit5)) == 1;
    }

    /**
     * 托盘降极限
     *
     * @return
     */
    public boolean palletDownOverrun() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit6)) == 1;
    }

    /**
     * 2向车/提升机未到位
     *
     * @return
     */
    public boolean lifterArrive() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit7)) == 1;
    }

    /**
     * 与外部主控系统通讯失败
     *
     * @return
     */
    public boolean controlNoConnect() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit8)) == 1;
    }

    /**
     * 提升机1轴报警
     *
     * @return
     */
    public boolean oneAxleErr() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit9)) == 1;
    }

    /**
     * 提升机2轴报警
     *
     * @return
     */
    public boolean twoAxleErr() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit10)) == 1;
    }

    /**
     * 提升机3轴报警
     *
     * @return
     */
    public boolean threeAxleErr() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit11)) == 1;
    }

    /**
     * 提升机4轴报警
     *
     * @return
     */
    public boolean fourAxleErr() {
        return readPlc(new PlcOffset(TWO_DIRECTION_RGV_ERR.getAddressOffset(), bit12)) == 1;
    }

    /**
     * 提升机两向车取货故障
     *
     * @return
     */
    public boolean twoDirectionGetCargoErr() {
        return isChainFontError();
    }

    /**
     * 提升机两向车放货故障
     *
     * @return
     */
    public boolean twoDirectionPutCargoErr() {
        return isChainBackError();
    }

    /**
     * 自卸式提升机两边没有链条机,不存在运行或不运行,默认false
     *
     * @param floor    层 提升机内部的层传1-10任意数字
     * @param location 位置
     * @return true 运行
     */
    @Override
    public boolean isFacilityExisted(Integer floor, Location location) {
        return false;
    }

    /**
     * 写入提升机指定位置货物状态
     *
     * @param floor      提升机层数
     * @param location   提升机位置(左、右)
     * @param cargoState 货物状态
     * @throws IOException
     */
    public void writeCargoState(Integer floor, Location location, CargoState cargoState) throws IOException {
        if (floor > 99 || floor < 1) {
            throw new IllegalArgumentException("输送线状态层数参数异常");
        }
        //1代表左对接层数,2代表右对接层数
        int floorNum = 0;
        if (Location.RIGHT == location || Location.LEFT == location) {
            // TODO: 2021/6/18 写货位状态
            if (Location.RIGHT == location) {
                floorNum = AbutmentLayer.RIGHT_ABUTMENT.getAbutmentLayer();
            } else if (Location.LEFT == location) {
                floorNum = AbutmentLayer.LEFT_ABUTMENT.getAbutmentLayer();
            }
            String cmd = "";
            cmd = "" + floor + floorNum + cargoState.getCargoState();
            super.oper("写入指定层货物状态", this.getClass(), WRITE_CARGO_STATE.getAddressOffset(), 10, Integer.valueOf(cmd));
        } else {
            LoggerUtil.error("提升机位置错误", this.getClass());
            throw new RuntimeException("提升机位置错误");
        }
    }

    /**
     * 读取货物是否清除标记
     *
     * @return
     */
    public boolean readCargoState() {
        return readPlc(CARGO_SIGN) == 0;
    }

    /**
     * 提升机任务一键恢复功能
     *
     * @throws IOException
     */
    public void lifterTaskRecover() throws IOException {
        super.oper("提升机任务一键恢复", this.getClass(), WRITE_TASK_RECOVER.getAddressOffset(), 10, 1);
    }
}
